gusucode.com > 各种VC自绘控件源码程序 > 各种VC自绘控件源码/code/SkinControls(自绘MFC基本控件 )/SkinControls/SkinControls/SkinRichEdit.cpp
#include "stdafx.h" #include "SkinRichEdit.h" #include "richole.h" #include "Resource.h" #include "SkinMenu.h" ////////////////////////////////////////////////////////////////////////// //宏定义 //菜单命令 #define IDM_CLEAR_ALL (WM_USER+201) //删除信息 #define IDM_SELECT_ALL (WM_USER+202) //全部选择 #define IDM_COPY_STRING (WM_USER+203) //拷贝字符 #define IDM_SAVE_STRING (WM_USER+205) //保存信息 #define IDM_DELETE_STRING (WM_USER+204) //删除字符 ////////////////////////////////////////////////////////////////////////// //构造函数 CImageDataObject::CImageDataObject() { //内核变量 m_ulRefCnt=0; ZeroMemory(&m_StgMedium,sizeof(m_StgMedium)); ZeroMemory(&m_FormatEtc,sizeof(m_FormatEtc)); //设置接口 m_pIStorage=NULL; m_pIOleObject=NULL; return; } //析构函数 CImageDataObject::~CImageDataObject() { //释放对象 ::ReleaseStgMedium(&m_StgMedium); //释放对象 if (m_pIOleObject!=NULL) m_pIOleObject->Release(); if (m_pIStorage!=NULL) m_pIStorage->Release(); return; } //增加引用 ULONG STDMETHODCALLTYPE CImageDataObject::AddRef() { m_ulRefCnt++; return m_ulRefCnt; } //释放对象 ULONG STDMETHODCALLTYPE CImageDataObject::Release() { if (--m_ulRefCnt==0) delete this; return m_ulRefCnt; } //查询接口 HRESULT STDMETHODCALLTYPE CImageDataObject::QueryInterface(REFIID iid, VOID * * ppvObject) { //查询接口 if (iid==IID_IUnknown||iid==IID_IDataObject) { *ppvObject=this; AddRef(); return S_OK; } return E_NOINTERFACE; } //获取数据 HRESULT STDMETHODCALLTYPE CImageDataObject::GetData(FORMATETC * pFormatEtcIn, STGMEDIUM * pStgMedium) { //状态判断 ASSERT(m_StgMedium.hBitmap!=NULL); if (m_StgMedium.hBitmap==NULL) return E_HANDLE; //获取数据 HANDLE hHandle=OleDuplicateData(m_StgMedium.hBitmap,CF_BITMAP,0); if (hHandle==NULL) return E_HANDLE; //设置变量 pStgMedium->tymed=TYMED_GDI; pStgMedium->pUnkForRelease=NULL; pStgMedium->hBitmap=(HBITMAP)hHandle; return S_OK; } //设置数据 HRESULT STDMETHODCALLTYPE CImageDataObject::SetData(FORMATETC * pFormatEtc, STGMEDIUM * pStgMedium, BOOL fRelease) { //设置变量 m_FormatEtc=*pFormatEtc; m_StgMedium=*pStgMedium; return S_OK; } //设置图片 bool CImageDataObject::SetImage(HBITMAP hBitmap) { //对象信息 m_StgMedium.tymed=TYMED_GDI; m_StgMedium.hBitmap=hBitmap; m_StgMedium.pUnkForRelease=NULL; //对象信息 m_FormatEtc.ptd=NULL; m_FormatEtc.lindex=-1; m_FormatEtc.tymed=TYMED_GDI; m_FormatEtc.cfFormat=CF_BITMAP; m_FormatEtc.dwAspect=DVASPECT_CONTENT; return true; } //加载图片 bool CImageDataObject::LoadImage(LPCTSTR pszFileName) { HBITMAP hbit = (HBITMAP)::LoadImage(NULL, pszFileName, IMAGE_BITMAP,0, 0, LR_LOADFROMFILE); //结果判断 if (hbit == NULL) { ASSERT(FALSE); return false; } //设置图片 SetImage(hbit); return true; } //加载图片 bool CImageDataObject::LoadImage(HINSTANCE hInstance, LPCTSTR lpBitmapName) { //加载图片 HBITMAP hBitmap=NULL; hBitmap=LoadBitmap(hInstance,lpBitmapName); //设置图片 SetImage(hBitmap); return true; } //获取信息 bool CImageDataObject::IntercalateReObject(REOBJECT & ReObject, IOleClientSite * pIOleClientSite) { //状态判断 ASSERT(m_StgMedium.hBitmap!=NULL); if (m_StgMedium.hBitmap==NULL) return false; //创建对象 if ((m_pIOleObject==NULL)||(m_pIStorage==NULL)) { try { //创建存储 LPLOCKBYTES lpLockBytes=NULL; CreateILockBytesOnHGlobal(NULL,TRUE,&lpLockBytes); StgCreateDocfileOnILockBytes(lpLockBytes,STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE,0,&m_pIStorage); //创建对象 OleCreateStaticFromData(this,IID_IOleObject,OLERENDER_FORMAT,&m_FormatEtc,NULL,m_pIStorage,(VOID * *)&m_pIOleObject); OleSetContainedObject(m_pIOleObject,TRUE); //对象效验 ASSERT((m_pIOleObject!=NULL)&&(m_pIStorage!=NULL)); if ((m_pIOleObject==NULL)||(m_pIStorage==NULL)) throw 0; } catch (...) { //释放对象 if (m_pIOleObject!=NULL) { m_pIOleObject->Release(); m_pIOleObject=NULL; } //释放对象 if (m_pIStorage!=NULL) { m_pIStorage->Release(); m_pIStorage=NULL; } return false; } } //设置变量 ZeroMemory(&ReObject,sizeof(ReObject)); //属性信息 ReObject.cbStruct=sizeof(ReObject); ReObject.cp=REO_CP_SELECTION; ReObject.dvaspect=DVASPECT_CONTENT; m_pIOleObject->GetUserClassID(&ReObject.clsid); //接口信息 ReObject.pstg=m_pIStorage; ReObject.poleobj=m_pIOleObject; ReObject.polesite=pIOleClientSite; return true; } ////////////////////////////////////////////////////////////////////////// BEGIN_MESSAGE_MAP(CSkinRichEdit, CRichEditCtrl) ON_WM_CREATE() ON_WM_DESTROY() ON_WM_SETCURSOR() ON_WM_RBUTTONDOWN() ON_COMMAND(IDM_CLEAR_ALL, OnClearAll) ON_COMMAND(IDM_SELECT_ALL, OnSelectAll) ON_COMMAND(IDM_COPY_STRING, OnCopyString) ON_COMMAND(IDM_SAVE_STRING, OnSaveString) ON_COMMAND(IDM_DELETE_STRING, OnDeleteString) END_MESSAGE_MAP() ////////////////////////////////////////////////////////////////////////// //构造函数 CSkinRichEdit::CSkinRichEdit() { //设置变量 m_pIRichEditOle=NULL; return; } //析构函数 CSkinRichEdit::~CSkinRichEdit() { //释放对象 if (m_pIRichEditOle!=NULL) { m_pIRichEditOle->Release(); m_pIRichEditOle=NULL; } return; } //控件绑定 VOID CSkinRichEdit::PreSubclassWindow() { __super::PreSubclassWindow(); //初始化控件 SetEventMask(ENM_LINK); SetOptions(ECOOP_OR,ECO_NOHIDESEL); //获取接口 m_pIRichEditOle=GetIRichEditOle(); return; } //创建消息 INT CSkinRichEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (__super::OnCreate(lpCreateStruct)==-1) return -1; //初始化控件 SetEventMask(ENM_LINK); SetOptions(ECOOP_OR,ECO_NOHIDESEL); //获取接口 m_pIRichEditOle=GetIRichEditOle(); return 0; } //清除屏幕 bool CSkinRichEdit::CleanScreen() { //清除屏幕 SetSel(0,GetWindowTextLength()); ReplaceSel(TEXT("")); return true; } //加载消息 bool CSkinRichEdit::LoadMessage(LPCTSTR pszFileName) { //效验参数 ASSERT(pszFileName!=NULL); if (pszFileName==NULL) return false; //打开文件 CFile File; if (File.Open(pszFileName,CFile::modeRead,NULL)==FALSE) return false; //构造数据 EDITSTREAM EditStream; EditStream.pfnCallback=LoadCallBack; EditStream.dwCookie=(DWORD)(LONGLONG)(&File); //读取文件 StreamIn(SF_RTF,EditStream); return true; } //保存消息 bool CSkinRichEdit::SaveMessage(LPCTSTR pszFileName) { //变量定义 CString strFileName=pszFileName; //打开文件 if (strFileName.IsEmpty()==true) { CFileDialog FileDlg(FALSE,TEXT("RTF"),0,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,TEXT("信息文件(*.RTF)|*.RTF||"),this); if (FileDlg.DoModal()==IDOK) strFileName=FileDlg.GetPathName(); else return true; } //打开文件 CFile File; if (File.Open(strFileName,CFile::modeWrite|CFile::modeCreate,NULL)==FALSE) return false; //构造数据 EDITSTREAM EditStream; EditStream.pfnCallback=SaveCallBack; EditStream.dwCookie=(DWORD)(LONGLONG)(&File); //写入文件 StreamOut(SF_RTF,EditStream); return true; } //插入图片 bool CSkinRichEdit::InsertImage(CBitmap * pBitmap) { //构造对象 CImageDataObject ImageDataObject; ImageDataObject.SetImage((HBITMAP)pBitmap->GetSafeHandle()); //插入图片 InsertDataObject(&ImageDataObject); return false; } //插入图片 bool CSkinRichEdit::InsertImage(LPCTSTR pszFileName) { //构造对象 CImageDataObject ImageDataObject; ImageDataObject.LoadImage(pszFileName); //插入图片 InsertDataObject(&ImageDataObject); return false; } //插入图片 void CSkinRichEdit::InsertGif( CString strPicPath ) { //变量定义 LPLOCKBYTES lpLockBytes = NULL; SCODE sc; HRESULT hr; LPOLECLIENTSITE lpClientSite; IGifAnimatorPtr lpAnimator; LPSTORAGE lpStorage; LPOLEOBJECT lpObject; //申请资源 sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); if (sc != S_OK) AfxThrowOleException(sc); ASSERT(lpLockBytes != NULL); sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage); if (sc != S_OK) { VERIFY(lpLockBytes->Release() == 0); lpLockBytes = NULL; AfxThrowOleException(sc); } ASSERT(lpStorage != NULL); //获取接口 GetIRichEditOle()->GetClientSite(&lpClientSite); ASSERT(lpClientSite != NULL); try { //I初始接口 hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); if( FAILED(hr) ) _com_issue_error(hr); //获取对象 hr = lpAnimator.CreateInstance(CLSID_GifAnimator); if( FAILED(hr) ) _com_issue_error(hr); //转换对象 BSTR path = strPicPath.AllocSysString(); //加载图片 hr = lpAnimator->LoadFromFile(path); if( FAILED(hr) ) _com_issue_error(hr); TRACE0( lpAnimator->GetFilePath() ); //获取对象 hr = lpAnimator.QueryInterface(IID_IOleObject, (void**)&lpObject); if( FAILED(hr) ) _com_issue_error(hr); OleSetContainedObject(lpObject, TRUE); REOBJECT reobject; ZeroMemory(&reobject, sizeof(REOBJECT)); reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; sc = lpObject->GetUserClassID(&clsid); if (sc != S_OK) AfxThrowOleException(sc); //设置变量 reobject.clsid = clsid; reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.dwFlags = REO_BELOWBASELINE; reobject.dwUser = 0; reobject.poleobj = lpObject; reobject.polesite = lpClientSite; reobject.pstg = lpStorage; SIZEL sizel; sizel.cx = sizel.cy = 0; reobject.sizel = sizel; HWND hWndRT = this->m_hWnd; GetIRichEditOle()->InsertObject(&reobject); ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0); VARIANT_BOOL ret; ret = lpAnimator->TriggerFrameChange(); //显示图片 lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, lpClientSite, 0, m_hWnd, NULL); lpObject->DoVerb(OLEIVERB_SHOW, NULL, lpClientSite, 0, m_hWnd, NULL); //更新窗体 RedrawWindow(); //释放接口 if (lpClientSite) { lpClientSite->Release(); lpClientSite = NULL; } if (lpObject) { lpObject->Release(); lpObject = NULL; } if (lpStorage) { lpStorage->Release(); lpStorage = NULL; } SysFreeString(path); } catch( _com_error e ) { ::CoUninitialize(); //Bmp显示 try{ CxImage Image; if ( SUCCEEDED(Image.Load(strPicPath)) ) { CBitmap Bitmap; Bitmap.Attach(Image.MakeBitmap()); InsertImage(&Bitmap); Bitmap.Detach(); } } catch(...){} } } //插入对象 bool CSkinRichEdit::InsertDataObject(CImageDataObject * pImageDataObject) { //效验参数 ASSERT((m_pIRichEditOle!=NULL)&&(pImageDataObject!=NULL)); if ((m_pIRichEditOle==NULL)||(pImageDataObject==NULL)) return false; //保存信息 CHARRANGE CharRange; GetSel(CharRange); //变量定义 IOleClientSite * pIOleClientSite=NULL; bool bResumeSelect=(CharRange.cpMax!=CharRange.cpMin); //填充信息 REOBJECT ReObject; ZeroMemory(&ReObject,sizeof(ReObject)); m_pIRichEditOle->GetClientSite(&pIOleClientSite); //插入图片 if (pImageDataObject->IntercalateReObject(ReObject,pIOleClientSite)==true) { //插入图片 SetSel(-1L,-1L); m_pIRichEditOle->InsertObject(&ReObject); //恢复信息 if (bResumeSelect==true) SetSel(CharRange); else PostMessage(WM_VSCROLL,SB_BOTTOM,0); } //释放对象 if (pIOleClientSite!=NULL) pIOleClientSite->Release(); return true; } //插入字串 bool CSkinRichEdit::InsertString(LPCTSTR pszString, COLORREF crTextColor) { //变量定义 CHARFORMAT2 CharFormat; ZeroMemory(&CharFormat,sizeof(CharFormat)); //构造数据 CharFormat.cbSize=sizeof(CharFormat); CharFormat.dwMask=CFM_COLOR; CharFormat.crTextColor=crTextColor; //插入字串 InsertString(pszString,CharFormat); return true; } //插入字串 bool CSkinRichEdit::InsertString(LPCTSTR pszString, COLORREF crTextColor, COLORREF crBackColor) { //变量定义 CHARFORMAT2 CharFormat; ZeroMemory(&CharFormat,sizeof(CharFormat)); //构造数据 CharFormat.cbSize=sizeof(CharFormat); CharFormat.dwMask=CFM_COLOR|CFM_BACKCOLOR; CharFormat.crTextColor=crTextColor; CharFormat.crBackColor=crBackColor; //插入字串 InsertString(pszString,CharFormat); return true; } //插入字串 bool CSkinRichEdit::InsertHyperLink(LPCTSTR pszString) { //变量定义 CHARFORMAT2 CharFormat; ZeroMemory(&CharFormat,sizeof(CharFormat)); //构造数据 CharFormat.cbSize=sizeof(CharFormat); CharFormat.dwMask=CFM_LINK; CharFormat.dwEffects=CFE_LINK; //插入字串 InsertString(pszString,CharFormat); return true; } //插入字串 bool CSkinRichEdit::InsertHyperLink(LPCTSTR pszString, COLORREF crBackColor) { //变量定义 CHARFORMAT2 CharFormat; ZeroMemory(&CharFormat,sizeof(CharFormat)); //构造数据 CharFormat.cbSize=sizeof(CharFormat); CharFormat.dwMask=CFM_BACKCOLOR|CFM_LINK; CharFormat.dwEffects=CFE_LINK; CharFormat.crBackColor=crBackColor; //插入字串 InsertString(pszString,CharFormat); return true; } //设置光标 BOOL CSkinRichEdit::OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT uMessage) { //设置光标 if (nHitTest==HTCAPTION) { SetCursor(LoadCursor(NULL,MAKEINTRESOURCE(IDC_ARROW))); return TRUE; } return __super::OnSetCursor(pWnd,nHitTest,uMessage); } //插入字串 bool CSkinRichEdit::InsertString(LPCTSTR pszString, CHARFORMAT2 & CharFormat) { //变量定义 bool bResumeSelect; CHARRANGE CharRange; //保存状态 GetSel(CharRange.cpMin,CharRange.cpMax); bResumeSelect=(CharRange.cpMax!=CharRange.cpMin); //搜索变量 LPCTSTR pszHttp=TEXT("http://"); const INT nHttpLength=lstrlen(pszHttp); const INT nStringLength=lstrlen(pszString); //索引定义 INT nStringStart=0; INT nStringPause=0; //字符解释 for (INT i=0;i<nStringLength;i++) { //变量定义 INT nUrlPause=i; //地址判断 if (((i+nHttpLength)<nStringLength)&&(memcmp(&pszString[i],pszHttp,nHttpLength*sizeof(TCHAR))==0)) { //设置索引 nUrlPause=i+nHttpLength; //地址搜索 while (nUrlPause<nStringLength) { //字符判断 if (EfficacyUrlChar(pszString[nUrlPause])==true) { nUrlPause++; continue; } break; } } //终止字符 if (nUrlPause<=(i+nHttpLength)) nStringPause=(i+1); //插入字符 if ((i==(nStringLength-1))||(nUrlPause>(i+nHttpLength))) { //普通字符 if (nStringPause>nStringStart) { //获取缓冲 CString strNormalString; LPTSTR pszNormalString=strNormalString.GetBuffer(nStringPause-nStringStart+1); //拷贝字符 pszNormalString[nStringPause-nStringStart]=0; CopyMemory(pszNormalString,&pszString[nStringStart],(nStringPause-nStringStart)*sizeof(TCHAR)); //释放缓冲 strNormalString.ReleaseBuffer(); //插入消息 SetSel(-1L,-1L); SetWordCharFormat(CharFormat); ReplaceSel((LPCTSTR)strNormalString); } //连接地址 if (nUrlPause>(i+nHttpLength)) { //获取缓冲 CString strUrlString; LPTSTR pszUrlString=strUrlString.GetBuffer((nUrlPause-i)+1); //拷贝字符 pszUrlString[nUrlPause-i]=0; CopyMemory(pszUrlString,&pszString[i],(nUrlPause-i)*sizeof(TCHAR)); //释放缓冲 strUrlString.ReleaseBuffer(); //构造格式 CHARFORMAT2 CharFormatHyper; CharFormatHyper=CharFormat; //效验地址 if (EfficacyUrlString(strUrlString)==true) { CharFormatHyper.dwMask|=CFM_LINK; CharFormatHyper.dwEffects|=CFE_LINK; } //插入消息 SetSel(-1L,-1L); SetWordCharFormat(CharFormatHyper); ReplaceSel((LPCTSTR)strUrlString); } //设置索引 nStringStart=__max(i,nUrlPause); } //设置索引 i+=(nUrlPause-i); } //状态设置 if (bResumeSelect==true) SetSel(CharRange); else PostMessage(WM_VSCROLL,SB_BOTTOM,0); return true; } //加载回调 DWORD CALLBACK CSkinRichEdit::LoadCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) { //读取文件 *pcb=((CFile *)(LONGLONG)(dwCookie))->Read(pbBuff,cb); return 0; } //保存回调 DWORD CALLBACK CSkinRichEdit::SaveCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) { //写入文件 ((CFile *)(LONGLONG)(dwCookie))->Write(pbBuff,cb); return 0; } //字符判断 bool CSkinRichEdit::EfficacyUrlChar(TCHAR chChar) { //特殊字符 if (chChar==TEXT('.')) return true; if (chChar==TEXT('=')) return true; if (chChar==TEXT('+')) return true; if (chChar==TEXT('?')) return true; if (chChar==TEXT('#')) return true; if (chChar==TEXT('%')) return true; if (chChar==TEXT('/')) return true; if (chChar==TEXT(':')) return true; if (chChar==TEXT('&')) return true; //字符范围 if ((chChar>=TEXT('a'))&&(chChar<=TEXT('z'))) return true; if ((chChar>=TEXT('A'))&&(chChar<=TEXT('Z'))) return true; if ((chChar>=TEXT('0'))&&(chChar<=TEXT('9'))) return true; return false; } //地址判断 bool CSkinRichEdit::EfficacyUrlString(LPCTSTR pszUrl) { return true; } //销毁消息 VOID CSkinRichEdit::OnDestroy() { __super::OnDestroy(); //释放接口 if (m_pIRichEditOle!=NULL) { m_pIRichEditOle->Release(); m_pIRichEditOle=NULL; } return; } //右键消息 VOID CSkinRichEdit::OnRButtonDown(UINT nFlags, CPoint Point) { //设置焦点 SetFocus(); CSkinMenu PopMenu; //建立菜单 PopMenu.CreatePopupMenu(); PopMenu.AppendMenu(0,IDM_COPY_STRING,TEXT("复制")); PopMenu.AppendMenu(0,IDM_SELECT_ALL,TEXT("全选")); PopMenu.AppendMenu(0,IDM_DELETE_STRING,TEXT("删除")); PopMenu.AppendMenu(0,IDM_CLEAR_ALL,TEXT("清除屏幕")); //PopMenu.AppendMenu(MF_SEPARATOR); //PopMenu.AppendMenu(0,IDM_SAVE_STRING,TEXT("保存信息")); //设置菜单 UINT nSel=((GetSelectionType()!=SEL_EMPTY)?0:MF_GRAYED); PopMenu.EnableMenuItem(IDM_COPY_STRING,MF_BYCOMMAND|nSel); PopMenu.EnableMenuItem(IDM_DELETE_STRING,MF_BYCOMMAND|nSel); PopMenu.EnableMenuItem(IDM_SELECT_ALL,MF_BYCOMMAND); //显示菜单 ClientToScreen(&Point); PopMenu.TrackPopupMenu(TPM_RIGHTBUTTON,Point.x,Point.y,this); PopMenu.DestroyMenu(); return; } //删除信息 VOID CSkinRichEdit::OnClearAll() { //删除信息 SetSel(0L,-1L); ReplaceSel(NULL); return; } //全部选择 VOID CSkinRichEdit::OnSelectAll() { //全部选择 SetSel(0L,-1L); return; } //拷贝字符 VOID CSkinRichEdit::OnCopyString() { //拷贝字符 Copy(); return; } //保存信息 VOID CSkinRichEdit::OnSaveString() { //保存信息 SaveMessage(NULL); return; } //删除字符 VOID CSkinRichEdit::OnDeleteString() { //删除字符 ReplaceSel(TEXT("")); return; } //////////////////////////////////////////////////////////////////////////